<?php
declare (strict_types = 1);

namespace app\common\controller\cron;

use app\BaseController;
use app\common\model\CronModel;
use app\common\model\CronSchedulingLogModel;
use app\common\service\CronService;

/**
 * 计划任务执行类
 *
 * @Author tanruizheng
 * @DateTime 2021-07-19
 */
class Index extends BaseController
{

    public $cronCount = 0;//计划任务执行次数
    public $errorCount = 0;//计划任务执行异常次数

    /**
     * 计划任务执行入口
     *
     * @Author tanruizheng
     * @DateTime 2021-07-20
     * @return void
     */
    public function index(){
        $startTime = time();
        $lockFile = runtime_path().'lock.txt';
        if(is_writable($lockFile)){
            return json(['code' => 0, 'msg' => 'Cron is Locked!']);
        }else{
            //创建文件
            touch($lockFile);
        }
        ignore_user_abort(true);
        set_time_limit(0);
        try {
            //执行任务
            $this->runCron();
            //释放文件锁
            unlink($lockFile);
            $endTime = time();
            $usedTime = $endTime - $startTime;
            
            //记录任务调度
            $cronSchedulingLogModel = new CronSchedulingLogModel();
            $cronSchedulingLogModel->start_time = $startTime;
            $cronSchedulingLogModel->end_time = $endTime;
            $cronSchedulingLogModel->use_time = $usedTime;
            $cronSchedulingLogModel->cron_count = $this->cronCount;
            $cronSchedulingLogModel->error_count = $this->errorCount;
            $cronSchedulingLogModel->save();
            return json(['code' => 1, 'msg' => '任务执行完成!' ,'used_time' => $usedTime]);
        } catch (\Exception $e) {
            //释放文件锁
            unlink($lockFile);
            return json(['code' => 0, 'msg' => $e->getMessage()]);
        }
    }

    public function runCron(){
        try {
            $cronModel = CronModel::where('next_time','<',time())
                ->where('isopen',CronModel::IS_OPEN_YES)
                ->order('next_time asc')
                ->findOrEmpty();
            if($cronModel->isEmpty()){
                return false;
            }
            //计划任务执行次数
            $this->cronCount++;
            //记录下次执行时间
            $loopDaytime = $cronModel->loop_daytime;
            list($day,$hour,$minute) = explode('-',$loopDaytime);
            $day = intval($day);
            $hour = intval($hour);
            $minute = intval($minute);
            $nextTime = CronService::getNextTime($cronModel->loop_type,$day,$hour,$minute);
            CronModel::where('cron_id',$cronModel->cron_id)->save([
                'modified_time' => time(),
                'next_time' => $nextTime
            ]);
            //执行任务执行文件的run方法
            $res = CronService::runAction($cronModel);
            if(!$res){
                //计划任务执行异常次数
                $this->errorCount++;
            }
            $this->runCron();
            return true;
        } catch (\Exception $e) {
            return false;
        }
    }
    
}